package com.wrx.club_management_backend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wrx.club_management_backend.common.AjaxResult;
import com.wrx.club_management_backend.dto.LoginFormDTO;
import com.wrx.club_management_backend.dto.UserDTO;
import com.wrx.club_management_backend.dto.UserSearchDTO;
import com.wrx.club_management_backend.entity.News;
import com.wrx.club_management_backend.entity.User;
import com.wrx.club_management_backend.mapper.ClubActivityMapper;
import com.wrx.club_management_backend.mapper.ClubMapper;
import com.wrx.club_management_backend.mapper.NewsMapper;
import com.wrx.club_management_backend.mapper.UserMapper;
import com.wrx.club_management_backend.service.UserService;
import com.wrx.club_management_backend.utils.RegexUtils;
import com.wrx.club_management_backend.utils.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.wrx.club_management_backend.utils.RedisConstant.*;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    StringRedisTemplate stringTemplate;

    @Autowired
    UserMapper userMapper;

    @Autowired
    ClubActivityMapper activityMapper;

    @Autowired
    NewsMapper newsMapper;

    /**
     * 登录方法
     * @param loginFormDTO
     * @return
     */
    @Override
    public AjaxResult login( LoginFormDTO loginFormDTO) {
        // 1. 检查手机号是否合法
        if (RegexUtils.isSNOInvalid(loginFormDTO.getSno())) {
            return AjaxResult.error("学号格式错误");
        }
        //2. 开始登录
        //3. 判断密码是否为空
        if (loginFormDTO.getPassword() == null || loginFormDTO.getPassword().isEmpty()) {
            return AjaxResult.error("密码不能为空");
        }
        User one = this.lambdaQuery().eq(User::getSno, loginFormDTO.getSno()).  one();
        if (!one.getPassword().equals(loginFormDTO.getPassword())) {
            return AjaxResult.error("密码错误");
        }
//        if(one.getStatus() == 0) return AjaxResult.error("该用户不存在"); // 逻辑删除
        //4. 在redis中添加登录的信息
        String token = UUID.randomUUID().toString(true); // 获取 token
        UserDTO dto = BeanUtil.copyProperties(one, UserDTO.class); // 用户数据模型
        stringTemplate.opsForHash().putAll(
                LOGIN_USER_KEY + token,
                BeanUtil.beanToMap(
                        dto,
                        new HashMap<>(),
                        CopyOptions.create()
                                .setIgnoreNullValue(true)
                                .setFieldValueEditor((fileName, fieldValue) -> fieldValue != null ? fieldValue.toString() : null)
                )
        );
        stringTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_KEY_TTL, TimeUnit.MINUTES); // 10分钟过期

        stringTemplate.opsForSet().add(LOGIN_STATUS, one.getId().toString());
        AjaxResult res = new AjaxResult();
        res.put("token", token);
        res.put("user", dto);
        res.put("code", 200);
        return res;
    }

//    @Override
//    public AjaxResult adminLogin(LoginFormDTO loginFormDTO) {
//        // 1. 检查手机号是否合法
//        if (RegexUtils.isPhoneInvalid(loginFormDTO.getPhone())) {
//            return AjaxResult.error("手机号码格式错误");
//        }
//        //2. 开始登录
//        //3. 判断密码是否为空
//        if (loginFormDTO.getPassword() == null || loginFormDTO.getPassword().isEmpty()) {
//            return AjaxResult.error("密码不能为空");
//        }
//        User one = this.lambdaQuery().eq(User::getPhone, loginFormDTO.getPhone()).one();
//        if (!one.getPassword().equals(loginFormDTO.getPassword())) {
//            return AjaxResult.error("密码错误");
//        }
//        if(one.getRole() != 2){
//            return AjaxResult.error("登录错误");
//        }
//        //4. 在redis中添加登录的信息
//        String token = UUID.randomUUID().toString(true); // 获取 token
//        UserDTO dto = BeanUtil.copyProperties(one, UserDTO.class); // 用户数据模型
//        stringTemplate.opsForHash().putAll(
//                LOGIN_USER_KEY + token,
//                BeanUtil.beanToMap(
//                        dto,
//                        new HashMap<>(),
//                        CopyOptions.create()
//                                .setIgnoreNullValue(true)
//                                .setFieldValueEditor((fileName, fieldValue) -> fieldValue != null ? fieldValue.toString() : null)
//                )
//        );
//        stringTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_KEY_TTL, TimeUnit.MINUTES); // 10分钟过期
//
//        stringTemplate.opsForSet().add(LOGIN_STATUS, one.getId().toString());
//        return AjaxResult.success(token);
//    }

    /**
     * 退出登录
     * @return
     */
    @Override
    public AjaxResult logout(HttpServletRequest request) {
        Long userId = UserHolder.getUser().getId();
        String token = request.getHeader("Authorization");
        stringTemplate.delete(LOGIN_USER_KEY + token);
        stringTemplate.opsForSet().remove(LOGIN_STATUS, userId.toString());
//        int a = 1 / 0; // 自己设置的Exception
        return AjaxResult.success("退出成功");
    }

    @Override
    public List<User> searchUsers(String keyword, String searchMode) {

        List<User> users = userMapper.searchUsers(keyword, searchMode);
        return users;
    }

    /**
     * 查询好友
     * @return
     */
    @Override
    public AjaxResult friends() {
        UserDTO user = UserHolder.getUser();
        List<Long> ids = stringTemplate
                .opsForSet()
                .members(FRIENDS_KEY + user.getId())
                .stream()
                .map(Long::parseLong)
                .collect(Collectors.toList());
        if(ids.isEmpty()) return AjaxResult.success(Collections.emptyList());
        List<User> users = this.listByIds(ids);
        users.forEach(item -> item.setOnline(isOnline(item.getId()))); // 给用户设置上登录状态
        return AjaxResult.success(users);
    }

    /**
     * 添加好友
     * @param id
     * @return
     */
    @Override
    public AjaxResult addFriend(Long id) {
        Long curId = UserHolder.getUser().getId();
        stringTemplate.opsForSet().add(FRIENDS_KEY + curId, id.toString());
        stringTemplate.opsForSet().add(FRIENDS_KEY + id, curId.toString());
        return AjaxResult.success("添加成功");
    }

    @Override
    public AjaxResult detail() {
        Long id = UserHolder.getUser().getId();
        User byId = this.getById(id);
        return AjaxResult.success(byId);
    }

    /**
     * 判断用户是否在线
     * @param id
     * @return
     */
    @Override
    public boolean isOnline(Long id) {
        return Boolean.TRUE.equals(stringTemplate.opsForSet().isMember(LOGIN_STATUS, id.toString()));
    }

    @Override
    public void updateUser(User user, String token) {
        UserDTO dto = new UserDTO();
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper
                .eq(User::getId, user.getId())
                .set(user.getNickname() != null , User::getNickname, user.getNickname())
                .set(user.getAvatar() != null || ! user.getAvatar().isEmpty() , User::getAvatar, user.getAvatar())
            .set( user.getDept() != null,  User::getDept, user.getDept())
                .set(user.getSno() != null , User::getSno, user.getSno());

        userMapper.update(null, updateWrapper);
        // 更新完后，要重新设置缓存
        dto.setNickname(user.getNickname());    dto.setAvatar(user.getAvatar()); dto.setPhone(user.getSno());
        Map<String, Object> map = BeanUtil.beanToMap(dto);
        stringTemplate.opsForHash().putAll(
                LOGIN_USER_KEY + token,
                BeanUtil.beanToMap(
                        dto,
                        new HashMap<>(),
                        CopyOptions.create()
                                .setIgnoreNullValue(true)
                                .setFieldValueEditor((fileName, fieldValue) -> fieldValue != null ? fieldValue.toString() : null)
                )
        );

    }

    /**
     * 删除好友
     * @param userId 好友 id
     * @return JSON
     */
    @Override
    public AjaxResult removeFriend(Long userId) {
        Long curId = UserHolder.getUser().getId();
        stringTemplate.opsForSet().remove(FRIENDS_KEY + curId, userId.toString());
        stringTemplate.opsForSet().remove(FRIENDS_KEY + userId, curId.toString());
        return AjaxResult.success("删除成功");
    }

    @Override
    public AjaxResult num() {
        int size = this.list().size();
        return AjaxResult.success(size);
    }

    @Override
    public AjaxResult register(User user) {
        //1. 先判断注册用户的手机号是否存在redis中
        Boolean tag = stringTemplate.opsForSet().isMember(SYS_SNO, user.getSno());
        if(!tag) return AjaxResult.error("手机号未录入系统，注册失败");
        // 如果注册的用户是管理员的话，就需要验证邀请码
        if(user.getRole() == 3){
            String code = user.getInviteCode();
            Boolean flag = stringTemplate.opsForSet().isMember(SYS_CODE, code);
            stringTemplate.opsForSet().remove(SYS_CODE, code); // 使用了就直接删除
            if(Boolean.FALSE.equals(flag)) return AjaxResult.error("邀请码错误");
        }
        this.save(user);
        return AjaxResult.success("注册成功");
    }

    @Override
    public boolean updatePassword(Long userId, String oldPassword, String newPassword) {
        return  this.update(
                new LambdaUpdateWrapper<User>()
                        .eq(User::getId, userId)
                        .eq(User::getPassword, oldPassword)
                        .set(User::getPassword, newPassword)
        );
    }

    @Override
    public void delUser(String phone) {
        // 删除用户
    }

    @Override
    public AjaxResult search(UserSearchDTO dto) {
        List<User> list = this.list(
                new LambdaQueryWrapper<User>()
                        .like(dto.getNickname() != null && !dto.getNickname().isEmpty(), User::getNickname, dto.getNickname())
                        .eq(dto.getRole() != null && dto.getRole() != 0, User::getRole, dto.getRole())
                        .like(dto.getPhone() != null && !dto.getPhone().isEmpty(), User::getSno, dto.getPhone())
        );
        return AjaxResult.success(list);
    }

    @Autowired
    ClubMapper clubMapper;


    /**
     * 删除用户
     * @return
     */
    @Override
    public AjaxResult delUser(Long userId) {
        //1. 删除用户参加的活动记录
       activityMapper.deleteParticipant(userId);
        //2. 删除用户与该用户相关的好友关系
        Set<String> members = stringTemplate.opsForSet().members(FRIENDS_KEY + userId);
        for (String member : members) {
            stringTemplate.opsForSet().remove(FRIENDS_KEY + member, userId);
        }
        stringTemplate.opsForSet().remove(FRIENDS_KEY + userId);
        //3. 删除用户的动态
        newsMapper.delete(
                new LambdaQueryWrapper<News>()
                        .eq(News::getUserId, userId)

        );
        //4. 从社团成员中删除
        clubMapper.deleteClubParticipate(userId);
        //5. 删除用户的社团
        clubMapper.deleteClubManager(userId);
        return AjaxResult.success("删除成功");
    }
}
